/**
 * Copyright (C) 2010 Neofonie GmbH
 *
 * This programm is free software; you can redistribute it and/or modify
 * it under the terms of the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package eu.dicode.analysis.demonstrator.util;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Iterator;

/**
 * Provides access to application configuration variables.
 */
public final class Configuration {
  /**Logger for this class.*/
  private static final Logger LOG = LoggerFactory.getLogger(Configuration.class);
  /**Strings that our configuration accepts as keys.*/
  public static final String DICODE_TOPIC_LOCK_LOCATION = "eu.dicodeproject.analysis.topics.lock.location";
  public static final String DICODE_DEFAULT_TOPIC_LOCK_LOCATION = "/tmp/dicode.topics.lck";
  public static final String DICODE_TOPIC_LOCATION = "eu.dicodeproject.analysis.topics.file.location";
  public static final String DICODE_DEFAULT_TOPIC_LOCATION = "/etc/tmp/topics.xml";
  public static final String DICODE_HISTOGRAM_LOCATION = "eu.dicodeproject.analysis.histogram.location";
  public static final String DICODE_DEFAULT_HISTOGRAM_LOCATION = "/etc/dicode/histogram-data";
  public static final String DICODE_COLLOCATION_LOCATION = "eu.dicodeproject.analysis.collocation.location";
  public static final String DICODE_DEFAULT_COLLOCATION_LOCATION = "/etc/dicode/collocation-data";

  /**Singleton instance*/
  private static Configuration configurationInstance;
  /**Configuration object*/
  private PropertiesConfiguration configuration;

  /** Make constructor private to ensure singleton property.*/
  private Configuration()  {
    try {
      this.configuration = new PropertiesConfiguration("dicode.analysis.demonstrator.user.properties");
    } catch (ConfigurationException e) {
      LOG.warn(
          "Loading user configuration dicode.analysis.demonstrator.user.properties failed. Continuing processing with values shipped with initial release. " + e.getMessage());
      LOG.debug("Detailed error message for failed properties loading: ", e);
    }
    try {
      if (this.configuration != null) {
        this.configuration.load("dicode.analysis.demonstrator.properties");
      } else {
        this.configuration = new PropertiesConfiguration("dicode.analysis.demonstrator.properties");
      }
    } catch (ConfigurationException e) {
      LOG.warn(
          "Loading configuration dicode.analysis.demonstrator.properties failed. Continuing processing with default values."
          + e.getMessage());
      LOG.debug("Detailed error message: ", e);
      this.configuration = null;
    }

    if (LOG.isDebugEnabled()) {
      Iterator<String> keyIter = this.configuration.getKeys();
      StringBuilder builder = new StringBuilder();
      while (keyIter.hasNext()) {
        String key = keyIter.next();
        builder.append(key).append(":").append(this.configuration.getString(key)).append("; ");
      }
      LOG.debug("Effective properties: " + builder.toString());
    }
  }

  /**
   * Returns the single instance of this configuration object.
   * */
  public static synchronized Configuration getInstance() {
    if (configurationInstance == null) {
      configurationInstance = new Configuration();
    }
    return configurationInstance;
  }

  /**
   * Retrieve a configuration value, returns the default value, if non was found in the config file.
   * @param key the configuration key
   * @param defaultValue the default value to fall back to
   * @return defaultValue if no value matching key was found, otherwise the value found in the configuration object.
   * */
  public int getIntValue(String key, int defaultValue) {
    if (configuration != null) {
      return configuration.getInt(key, defaultValue);
    } else {
      return defaultValue;
    }
  }

    /**
   * Retrieve a configuration value, returns the default value, if non was found in the config file.
   * @param key the configuration key
   * @param defaultValue the default value to fall back to
   * @return defaultValue if no value matching key was found, otherwise the value found in the configuration object.
   * */
  public String getStringValue(final String key, final String defaultValue) {
    String result = defaultValue;
    if (configuration != null) {
      result = configuration.getString(key, defaultValue);
    }
    LOG.info("For key: " + key + " returning value: " + result);
    return result;
  }
}
